package org.huoran.sakamichi.task;

import com.alibaba.fastjson.JSONObject;
import org.apache.log4j.PropertyConfigurator;
import org.huoran.sakamichi.main.util.HttpUtilWithProxy;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class SKJVoteTask {
    private static final org.slf4j.Logger logger  = LoggerFactory.getLogger(SKJVoteTask.class);

    // 投票任务配置
    private static Integer THREAD_POOL_SIZE;
    private static String TARGET_URL;
    private static Integer VOTE_NUMBER;
    private static Boolean NEED_BREAK;

    // 线程配置
    private static ExecutorService executorService;
    private static CountDownLatch countDownLatch;
    private static AtomicInteger CURRENT_VOTE_NUMBER = new AtomicInteger(0);

    // 返回值配置
    private static final String CODE_KEY = "code";
    private static final Integer VOTE_SUCCESS_CODE = 0;

    /**
     * 任务实例构造器
     * @param targetUrl
     * @param threadPoolSize
     * @param voteNumber
     * @param needBreak
     */
    SKJVoteTask(String targetUrl, Integer threadPoolSize, Integer voteNumber, Boolean needBreak){
        TARGET_URL = targetUrl;
        VOTE_NUMBER = voteNumber;
        THREAD_POOL_SIZE = threadPoolSize;
        NEED_BREAK = needBreak;
        executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        countDownLatch = new CountDownLatch(THREAD_POOL_SIZE);
    }

    /**
     * 开启投票
     */
    private void start(){
        MainTask mainTask = new MainTask();
        mainTask.run();
    }

    /**
     * 内部类实现主线程完成线程池并发任务
     */
    static class MainTask implements Runnable {

        MainTask(){
            logger.info("main : Started. Executing...");
            logger.info("------------ 0 / " + VOTE_NUMBER + " ------------");
        }

        /**
         * 线程池开启子任务
         */
        private void startExecutor(){
            for(int i=0;i<THREAD_POOL_SIZE;i++){
                executorService.submit(new VoteTask(i));
            }
        }

        @Override
        public void run() {
            int lastNumber = 0;
            boolean success = true;
            // 任务执行
            while(VOTE_NUMBER == null || CURRENT_VOTE_NUMBER.get() < VOTE_NUMBER){
                // 重新给主线程加锁
                countDownLatch = new CountDownLatch(THREAD_POOL_SIZE);
                long turnStart = new Date().getTime();
                // 阻塞等待子线程结束
                try {
                    startExecutor();
                    countDownLatch.await(5L,TimeUnit.SECONDS);
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                }
                // 统计子线程结果
                logger.info("------------ " + CURRENT_VOTE_NUMBER.get() + " / " + VOTE_NUMBER + " ------------");
                if(NEED_BREAK && (CURRENT_VOTE_NUMBER.get() == lastNumber)){
                    success = false;
                    break;
                }
                lastNumber = CURRENT_VOTE_NUMBER.get();
                // 等待下一轮请求
                while(new Date().getTime() - turnStart < 1000L){
                    try {
                        Thread.sleep(100L);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
            }
            // 任务结束
            if(success){
                logger.info("main : Finished. Shutting down...");
            }
            else{
                logger.info("main : Interrupted by error. Shutting down...");
            }
            // 关闭子线程池定时任务
            if(!executorService.isShutdown()){
                executorService.shutdown();
            }
        }
    }

    /**
     * 内部类实现子线程完成单线程投票
     */
    static class VoteTask implements Runnable {
        // 任务编号
        private Integer number = null;

        VoteTask(Integer number){
            this.number = number;
        }

        /**
         * 使用httpClient请求投票
         * @param targetUrl
         * @return
         */
        private JSONObject vote(String targetUrl){
            JSONObject result = HttpUtilWithProxy.doGetRequest(targetUrl);
            return result;
        }

        @Override
        public void run() {
            logger.info(this.number + " : Started. Executing...");
            // 投票未满
            if(VOTE_NUMBER == null || CURRENT_VOTE_NUMBER.get() < VOTE_NUMBER){
                JSONObject httpGetResult = vote(TARGET_URL);
                // 请求成功
                if(httpGetResult != null){
                    // 代理成功
                    if(httpGetResult.getInteger(HttpUtilWithProxy.STATUS_CODE_KEY) == 200){
                        String resultStr = httpGetResult.getString(HttpUtilWithProxy.RESULT_KEY);
                        JSONObject result = JSONObject.parseObject(resultStr);
                        // 投票成功
                        if(result.getInteger(CODE_KEY) == VOTE_SUCCESS_CODE){
                            CURRENT_VOTE_NUMBER.incrementAndGet();
                            logger.info(this.number + " : Vote success.");
                        }
                        // 投票失败
                        else{
                            logger.info(this.number + " : Vote failed.");
                        }
                    }
                    // 代理失败
                    else{
                        logger.info(this.number + " : Http request failed " +
                                httpGetResult.getInteger(HttpUtilWithProxy.STATUS_CODE_KEY) + ".");
                    }
                }
                // 请求失败
                else{
                    logger.info(this.number + " : Http time out.");
                }
            }
            // 投票已满
            else{
                logger.info(this.number + " : Finished.");
            }
            // 解锁主线程
            countDownLatch.countDown();
        }
    }

    public static void main(String[] args){
//        PropertyConfigurator.configure("E:\\IDEAspace\\sakamichi\\sakamichi-service\\src\\main\\resources\\properties\\log4j.properties");
        PropertyConfigurator.configure("F:\\IDEAspace\\sakamichi\\sakamichi-service\\src\\main\\resources\\properties\\log4j.properties");
        logger.info("--------- SKJVoteTask ---------");
        String targetUrl = "http://h5.damai.cn/drama/votePlayer?playerId=09";
        Integer threadPoolSize = 5;
        Integer voteNumber = 1000;
        Boolean needBreak = false;
        SKJVoteTask skjVoteCheater = new SKJVoteTask(targetUrl, threadPoolSize, voteNumber, needBreak);
        skjVoteCheater.start();
    }
}
